home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 001-100 / 001-025 / 010 / ls / wildexp.c < prev    next >
C/C++ Source or Header  |  1995-03-17  |  9KB  |  293 lines

  1. /*
  2. ** The following module contains functions which permit wildcard
  3. ** filename expansion using Unix type wildcard characters.  This
  4. ** module can be compiled separately and included in the link for
  5. ** any programs which desire it's support.  The following functions
  6. ** are present:
  7. **
  8. **   findfirst       - find the first occurance of a file matching
  9. **                     the given name which may contain Unix style
  10. **                     wildcards.
  11. **   findnext        - find the next occurance of a file.  Returns
  12. **                     0 if no more matches remain.
  13. **   find_cleanup    - release all storage and locks reserved by findfirst
  14. **                     and/or findnext.  MUST be called before exit!
  15. **   fferror         - given an error code returned by findnext, this
  16. **                     function returns a pointer to a descriptive
  17. **                     error message string.
  18. **   iswild          - given a string, this function returns
  19. **                     TRUE if the string contains a wildcard character
  20. **                     and FALSE if not.
  21. **   wildexp         - given a file name and a pointer to a table of
  22. **                     pointers, this function will fill the table
  23. **                     with a list of file names in the indicated
  24. **                     directory which match the given name.
  25. **
  26. ** 
  27. ** Written by:  Rick Schaeffer
  28. **              E. 13611 26th Ave.
  29. **              Spokane, Wa.  99216
  30. **              Compuserve ID: 70120,174
  31. **              Bytenet ID: ricks.
  32. */
  33.  
  34. #include "wildexp.h"
  35.  
  36. /*
  37. ** Return values for findfirst and findnext are:
  38. **  0 = retval ok, find struct "fname" contains name of file found
  39. **  1 = file name too long
  40. **  2 = error in parsing
  41. **  3 = invalid path name
  42. **  4 = first Examine failed
  43. **  5 = not a directory
  44. */
  45.  
  46. /* fferror -- return a meaningful error message for findxxx errors
  47. **  Parameter:
  48. **     errcd - An integer containing the error code returned by findfirst
  49. **             or findnext.
  50. **
  51. **  Returns:
  52. **     msgptr - A pointer to a meaningful error message
  53. */
  54. char *fferror(errcd)
  55. int errcd;
  56. {
  57.     static char *errmsg[] = {
  58.         "Filename too long",
  59.         "Filename invalid",
  60.         "Pathname invalid",
  61.         "Examine failed",
  62.         "Pathname invalid",
  63.         "Error code invalid"
  64.         };
  65.     
  66.     if (--errcd > 4)
  67.         errcd = 5;
  68.     return(errmsg[errcd]);
  69. }   
  70.  
  71. /* findfirst -- find the first occurance of a given file name in either
  72. **              the given or the current directory.
  73. **  Parameters:
  74. **    name - A pointer to a filename string.  May contain wildcard
  75. **           characters ('?' and/or '*').  May optionally contain
  76. **           a directory path.  Example: "df0:c/d*" matches all
  77. **           files in directory "df0:c" which begin with the letter
  78. **           "d".
  79. **    fwk  - A pointer to a structure which will be filled in by
  80. **           findfirst and used by findnext.  Must NOT be disturbed
  81. **           between calls!
  82. **
  83. **  Returns:
  84. **    0 = successful completion.  fwk filled in with first matching
  85. **        file.
  86. **   >0 = error code.  use fferror to obtain a meaningful description.
  87. **
  88. **  Example:
  89. **    findfirst("*.c",fwk)
  90. **       The first matching file is in fwk->fname.
  91. */
  92. findfirst(name,fwk)
  93. char    *name;
  94. struct find     *fwk;
  95. {
  96.     struct Process *tp,*FindTask();
  97.     int             pt[16];
  98.     int             last;
  99.     char            *p1,*strchr();
  100.  
  101.     fwk->fp = (struct FileInfoBlock *) AllocMem(sizeof(struct FileInfoBlock),0);
  102.         /* caller must free this space! */
  103.     fwk->flock = 0;
  104.     
  105.     if (strlen(name) > 128)
  106.         return(1); /* file name too long */
  107.     if ((p1 = strchr(name,':')) != NULL)
  108.         if (strchr(name,'/') == NULL) {
  109.             *p1 = 0;
  110.             strcpy(fwk->path,name);
  111.             strcat(fwk->path,":/");
  112.             strcat(fwk->path,p1+1);
  113.             strcpy(name,fwk->path);
  114.             }
  115.     strcpy(fwk->path,name);
  116.     if (stspfp(name,pt) == -1)
  117.         return(2);  /* error in parsing */
  118.     for (last=0; last < 16; last++)
  119.         if (pt[last] == -1)
  120.             break;
  121.     last--;     /* now points at file name portion */
  122.     if ((last == 0) && (pt[0] == 0)) {  /* no path */
  123.         if (strlen(name) > 32)
  124.             return(1); /* file name too long */
  125.         strcpy(fwk->name,name);
  126.         fwk->path[0] = 0;
  127.         tp = FindTask(NULL);
  128.         fwk->flock = DupLock(tp->pr_CurrentDir);
  129.         bldfull(fwk);   /* build full path name */
  130.         }
  131.     else {
  132.         if (strlen(&name[pt[last]]) > 32)
  133.             return(1); /* file name too long */
  134.         strcpy(fwk->name,&name[pt[last]]);
  135.         fwk->path[pt[last] - 1] = 0;
  136.         if ((fwk->flock = Lock(fwk->path,ACCESS_READ)) == 0)
  137.             return(3); /* invalid path name */
  138.         bldfull(fwk);
  139.         }
  140.     if (Examine(fwk->flock,fwk->fp)) {  /* get directory name */
  141.         if (fwk->fp->fib_DirEntryType > 0)
  142.             return(findnext(fwk));
  143.         else
  144.             return(5); /* not a directory */
  145.         }
  146.     else
  147.         return(4);  /* first examine failed */
  148. }
  149.  
  150. /*
  151. ** findnext -- find next occurance of a matching file.
  152. **  Parameter:
  153. **    fwk - pointer to a "find" structure which has been filled in
  154. **          by a call to findfirst.
  155. **
  156. **  Returns:
  157. **    0 = Match found.  fwk->fname contains the name.
  158. **   -1 = No more matches.
  159. */
  160. int findnext(fwk)
  161. struct find *fwk;
  162. {
  163.     while (ExNext(fwk->flock,fwk->fp)) {
  164.         strcpy(fwk->fname,fwk->fp->fib_FileName);
  165.         if (fnmatch(fwk->fname,fwk->name))
  166.             return(0);
  167.         }
  168.     return(-1);
  169. }
  170.  
  171. bldfull()
  172. {
  173. }
  174.  
  175. /* find_cleanup -- release any structures and locks used by findfirst.
  176. **   Parameters:
  177. **      fwk - pointer to a "find" structure which has been previously
  178. **            filled in by findfirst.
  179. **   Returns:
  180. **    nothing
  181. */
  182. find_cleanup(fwk)
  183. struct find *fwk;
  184. {
  185.     if (fwk->flock)
  186.         UnLock(fwk->flock);
  187.     if (fwk->fp)
  188.         FreeMem(fwk->fp,sizeof(struct FileInfoBlock));
  189. }
  190.  
  191. /* fnmatch -- perform unix style pattern match on a file name
  192. **   usage: result = fnmatch(name,pattern)
  193. **       returns 1 if "name" matches "pattern", 0 otherwise
  194. */
  195.  
  196. int fnmatch(name,pattern)
  197. register char   *name,*pattern;
  198. {
  199.  
  200.     while (*pattern) {
  201.         if (*pattern == '*') {
  202.             while (*pattern == '*')
  203.                 pattern++;
  204.             while ((*name) && (tolower(*name) != tolower(*pattern)))
  205.                 name++;
  206.             if (*name == 0)
  207.                 if (*pattern == 0)
  208.                     return(1);  /* matched */
  209.                 else
  210.                     return(0);
  211.             }
  212.         if (*pattern == '?') {
  213.             pattern++;
  214.             name++;
  215.             continue;
  216.             }
  217.         if (tolower(*pattern) != tolower(*name))
  218.             return(0); /* not matched */
  219.         pattern++;
  220.         name++;
  221.         }
  222.     if ((*name == 0) && (*pattern == 0))
  223.         return(1);  /* matched */
  224.     else
  225.         return(0);  /* not matched */
  226. }
  227.  
  228. /*
  229. ** wildexp -- expand a wildcard file name
  230. **  Parameters:
  231. **    name     - Pointer to the file name to be expanded.
  232. **    adtbl    - Pointer to an array of pointers.
  233. **    maxargs  - The maximum number of pointers contained in adtbl.
  234. **
  235. **  Returns:
  236. **    1 = Successful completion.  The adtbl array will contain pointers
  237. **        to all file names found and will be terminated with a NULL
  238. **        pointer.  It's use is exactly like use of the standard C
  239. **        argv array except that the first filename argument is in
  240. **        adtbl[0] whereas argv[0] contains a pointer to the name of
  241. **        the function which was invoked.
  242. **    0 = An error occured.
  243. */
  244. int wildexp(name,adtbl,maxargs)
  245. char            *name;
  246. register char   **adtbl;
  247. int             maxargs;
  248. {
  249.     struct find f;
  250.     register int i=0;
  251.     char        *malloc();
  252.     int     retval;
  253.  
  254.     if ((retval = findfirst(name,&f)) > 0) {
  255.         *adtbl = NULL;
  256.         find_cleanup(&f);
  257.         return(0);
  258.         }
  259.     while (retval == 0) {
  260.         if (f.fp->fib_DirEntryType > 0) {
  261.             retval=findnext(&f);
  262.             continue;   /* it's a directory */
  263.             }
  264.         *adtbl = malloc(strlen(f.path)+strlen(f.fname)+1);
  265.         if (*adtbl == NULL) {
  266.             find_cleanup(&f);
  267.             return(0);  /* arena is full */
  268.             }
  269.         strcpy(*adtbl,f.path);
  270.         if ((f.path[0] != 0) && (f.path[strlen(f.path)-1] != ':'))
  271.             strcat(*adtbl,"/");
  272.         strcat(*adtbl++,f.fname);
  273.         if ((++i) >= maxargs)
  274.             return(0);
  275.         retval=findnext(&f);
  276.         }
  277.     *adtbl = NULL;
  278.     find_cleanup(&f);
  279.     return(1);
  280. }
  281.  
  282. int iswild(s)
  283. char    *s;
  284. {
  285.     while (*s) {
  286.         if ((*s == '*') || (*s == '?'))
  287.             return(1);
  288.         s++;
  289.         }
  290.     return(0);
  291. }
  292.  
  293.